#include "mqtt_khd.h"
#include "c3_main.h"

// 全局默认主题
#define DEFAULT_TOPIC "cx/jia/ws/js" //接收消息
#define FASONG_TOPIC "cx/jia/ws/fs"  //发送消息

static uint16_t mqtt_chong_lian_ci_shu = 0;
//static bool wifiLianJie = true;   // WiFi连接标志,默认链接
static bool renWuBiaoZhi = false; // 是否有预定任务标志
static size_t xBytesSent;
static const TickType_t x100ms = pdMS_TO_TICKS(100);

static const char *TAG = "mqtt_example";
// 定义全局MQTT客户端句柄（或通过参数传递）
static esp_mqtt_client_handle_t s_mqtt_client = NULL;
static esp_mqtt_client_handle_t client = NULL;

// 生成唯一客户端ID
static char *get_unique_client_id(void)
{
    static char client_id[32];
    uint8_t mac[6];
    esp_wifi_get_mac(WIFI_IF_STA, mac); // 获取STA模式的MAC地址
    // 格式: "zhong_duan_xx:xx:xx:xx:xx:xx"
    snprintf(client_id, sizeof(client_id), "zhong_duan_%02x%02x%02x%02x%02x%02x",
             mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    return client_id;
}

static void log_error_if_nonzero(const char *message, int error_code)
{
    if (error_code != 0)
    {
        ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
    }
}

bool mqqt_publish(char *data)
{
    // 如果传入的topic为NULL，则使用默认主题
    // char* actual_topic = (topic == NULL) ? DEFAULT_TOPIC : topic;
    int msg__id;
    msg__id = esp_mqtt_client_publish(client, FASONG_TOPIC, data, 0, 1, 0);
    return (msg__id != -1); // 发布成功返回true，失败返回false
}

/*
 * @brief 注册用于接收 MQTT 事件的事件处理程序
 *
 *  此函数由 MQTT 客户端事件循环调用。
 *
 * @param handler_args user data registered to the event.
 * @param base Event base for the handler(always MQTT Base in this example).
 * @param event_id The id for the received event.
 * @param event_data The data for the event, esp_mqtt_event_handle_t.
 */
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
    esp_mqtt_event_handle_t event = event_data;
    client = event->client;
    int msg_id;
    switch ((esp_mqtt_event_id_t)event_id)
    {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        // 发布消息
        // msg_id = esp_mqtt_client_publish(client, "abc", "data_3", 0, 1, 0);

        // 订阅主题
        msg_id = esp_mqtt_client_subscribe(client, DEFAULT_TOPIC, 0);
        //msg_id = esp_mqtt_client_subscribe(client, FASONG_TOPIC, 0);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
        mqtt_chong_lian_ci_shu = 0;

        // msg_id = esp_mqtt_client_subscribe(client, "add", 1);
        break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED,将在5秒后尝试重连");
        vTaskDelay(pdMS_TO_TICKS(5000)); // 等待WiFi恢复
        mqtt_chong_lian_ci_shu++;
        if (mqtt_chong_lian_ci_shu > 120 && renWuBiaoZhi == true)
        {
            esp_restart(); // 重试失败后重启设备
        }
        /*
        // 可在此处添加自定义重连逻辑（如检查网络状态后再重连）
        if (wifiLianJie)
        {
            // 2. 调用start函数触发重连（客户端已初始化，只需重新启动）
            esp_err_t err = esp_mqtt_client_start(s_mqtt_client);
            if (err != ESP_OK)
            {
                ESP_LOGE(TAG, "手动重连失败: %s", esp_err_to_name(err));
                // 失败后可延时重试
                vTaskDelay(pdMS_TO_TICKS(2000));
            }
        }
        else
        {
            ESP_LOGW(TAG, "WiFi未连接,延迟重连...");
            vTaskDelay(pdMS_TO_TICKS(5000)); // 等待WiFi恢复
        }
            */
        break;

    case MQTT_EVENT_SUBSCRIBED://已订阅事件
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED://已取消订阅事件
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED://已发布事件
        //ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA://接收数据事件
        //ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        //% 是格式转换符的起始标志，用于告诉函数：“接下来的字符是格式控制指令，需要按照指定规则解析后续参数并输出
        //* 表示 “字段宽度由后面的参数指定”（即 event->topic_len 或 event->data_len）
        // s 表示打印字符串（即 event->topic 或 event->data）
        // printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);//主题
        // printf("DATA=%.*s\r\n", event->data_len, event->data);//数据
        // 将受到的数据发往消息缓冲区
        xBytesSent = xMessageBufferSend(zhuanFanP, (const void *)event->data, event->data_len, x100ms);
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT)
        {
            log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
            log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
            log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
            ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
        }
        break;
    default:
        ESP_LOGI(TAG, "Other event id:%d", event->event_id);
        break;
    }
}

static void mqtt_app_stop(void)
{
    if (s_mqtt_client)
    {
        esp_mqtt_client_stop(s_mqtt_client);
        esp_mqtt_client_destroy(s_mqtt_client);
        s_mqtt_client = NULL;
        ESP_LOGI(TAG, "MQTT客户端已停止");
    }
}

static void mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
        .broker.address.uri = "mqtt://192.168.1.88:1883",  // 完整URI：协议+IP+端口
        .credentials.username = "cx001",                   // 用户名
        .credentials.authentication.password = "cx123100", // 密码
        .credentials.client_id = get_unique_client_id(),   // 唯一ID
        //.keepalive = 60, // 心跳间隔60秒（默认120秒，可缩短提高检测灵敏度）
        //.network.disable_auto_reconnect = true // 禁用自动重连
    };

    s_mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
    // esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    /* 最后一个参数可用于将数据传递给事件处理程序，在本示例中为 mqtt_event_handler。 */
    esp_mqtt_client_register_event(s_mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    esp_err_t err = esp_mqtt_client_start(s_mqtt_client);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "启动MQTT客户端失败: %s", esp_err_to_name(err));
        mqtt_app_stop(); // 启动失败时释放资源
    }
}

void mqtt_init(void)
{
    ESP_LOGI(TAG, "[APP] Startup..");
    ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
    ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());

    esp_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
    esp_log_level_set("mqtt_example", ESP_LOG_VERBOSE);
    esp_log_level_set("transport_base", ESP_LOG_VERBOSE);
    esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
    esp_log_level_set("transport", ESP_LOG_VERBOSE);
    esp_log_level_set("outbox", ESP_LOG_VERBOSE);

    // ESP_ERROR_CHECK(esp_netif_init());
    esp_err_t err = esp_netif_init();
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "esp_netif_init 失败: %s (0x%x)", esp_err_to_name(err), err);
        // 增加重试逻辑或降级处理（例如延时后重启）
        vTaskDelay(pdMS_TO_TICKS(2000));
        esp_restart(); // 重试失败后重启设备
    }

    mqtt_app_start();
}